package server

import (
	"fmt"
	"server5/Interface"
	"server5/protobuf"
	"server5/utils"
	"strconv"
	"strings"
)

type Player struct {
	playerId    int32
	friendId	int32
	user 		Interface.IUser
	gameRoom    Interface.IGameRoom
	strongholds map[int32]Interface.IStronghold
	units       map[int32]Interface.IUnit
	maxPop		int32	//最大人口
	pop         int32	//当前人口
	money       int32	//金币数
	magic       int32	//魔法值
	moneyAdd    int32	//每秒增长的金币数
	magicAdd    int32	//每秒增长的魔法值

	MaxDamageLevel int32	//技能一等级
	MaxReplyHpLevel int32	//技能二等级
	MaxCallBossLevel int32	//技能三等级

	DamageLevel int32	//技能一等级
	ReplyHpLevel int32	//技能二等级
	CallBossLevel int32	//技能三等级
}

func (p *Player) ReSkillLevel() {
	var maxLevel int32 = 0
	for _,s := range p.strongholds {
		if s.Level() > maxLevel {
			maxLevel = s.Level()
		}
	}
	if maxLevel > p.MaxDamageLevel {
		p.DamageLevel = p.MaxDamageLevel
	} else {
		p.DamageLevel = maxLevel
	}
	if maxLevel > p.MaxReplyHpLevel {
		p.ReplyHpLevel = p.MaxReplyHpLevel
	} else {
		p.ReplyHpLevel = maxLevel
	}
	if maxLevel > p.MaxCallBossLevel {
		p.CallBossLevel = p.MaxCallBossLevel
	} else {
		p.CallBossLevel = maxLevel
	}
}

//重新计算人口数，金币和魔法增长
func (p *Player) ReCalculate() {
	p.pop = 0
	p.maxPop = utils.PlayerPop
	p.moneyAdd = utils.PlayerMoneyAdd
	p.magicAdd = utils.PlayerMagicAdd
	for _,s := range p.strongholds {
		s.ReCalculate()
		p.maxPop += s.Pop()
		p.moneyAdd += s.MoneyAdd()
		p.magicAdd += s.MagicAdd()
	}
	for _,u := range p.units {
		if u.UnitType() != utils.Boss {
			p.pop++
		}
	}
	if len(p.strongholds) == 0{
		p.moneyAdd = 0
		p.magicAdd = 0
	}
	fmt.Println("更新信息，金币，魔法，人口，总人口",p.moneyAdd,p.magicAdd,p.pop,p.maxPop)
}

func NewPlayer(user Interface.IUser,playerId int32,friendId int32, room Interface.IGameRoom) *Player{
	p := &Player{
		gameRoom: room,
		user: user,
		playerId: playerId,
		friendId: friendId,
		strongholds: make(map[int32]Interface.IStronghold),
		units: make(map[int32]Interface.IUnit),
		money: utils.PlayerMoney,
		moneyAdd: utils.PlayerMoneyAdd,
		pop: utils.PlayerPop,
		magic: utils.PlayerMagic,
		magicAdd: utils.PlayerMagicAdd,
		MaxDamageLevel: int32(user.UserInfo().DamageLevel),
		MaxReplyHpLevel: int32(user.UserInfo().ReplyHpLevel),
		MaxCallBossLevel: int32(user.UserInfo().CallBossLevel),

		DamageLevel: 1,
		ReplyHpLevel: 1,
		CallBossLevel: 1,
	}
	return p
}

//技能一，范围伤害 Damage
func (p *Player) Damage(unitIds string) bool {
	if unitIds == "" {
		fmt.Println("技能范围内没有目标")
		return false
	}
	switch p.DamageLevel {
	case 1:
		return p.DamageWork(unitIds,utils.DamageMagic1,utils.DamageValue1)
	case 2:
		return p.DamageWork(unitIds,utils.DamageMagic2,utils.DamageValue2)
	case 3:
		return p.DamageWork(unitIds,utils.DamageMagic3,utils.DamageValue3)
	}
	return false
}

func (p *Player) DamageWork(unitIds string,magic int32,value int32) bool{

	if p.magic >= magic {
		p.AddMagic(-magic)
		list := strings.Split(unitIds,",")
		units := p.gameRoom.Units()

		var attackUnitInfoMsg protobuf.AttackUnitInfoMsg

		for _, unitIdString := range list {
			unitId, _ := strconv.Atoi(unitIdString)
			unit, ok := units[int32(unitId)]
			if !ok {
				fmt.Println("没有这个单位，数据错误")
				return false
			}
			if unit.Player().PlayerId() == p.playerId || unit.Player().FriendId() == p.playerId {
				fmt.Println("技能攻击自己的小兵？")
				return false
			}
			unit.AddHp(-value)
			attackUnitInfoMsg.Id = unit.Id()
			attackUnitInfoMsg.NowHp = unit.NowHp()
			attackUnitInfoMsg.Status = unit.Status()
			if unit.AttackTarget() != nil {
				attackUnitInfoMsg.AttackId = unit.AttackTarget().Id()
			}
			p.gameRoom.Broadcast(protobuf.MsgType_AttackUnitInfo,&attackUnitInfoMsg)
		}
		return true
	}
	return false
}

//技能二，回血 ReplyHp
func (p *Player) ReplyHp() bool {

	switch p.ReplyHpLevel {
	case 1:
		return p.ReplyHpWork(utils.ReplyHpMagic1,utils.ReplyHpValue1)
	case 2:
		return p.ReplyHpWork(utils.ReplyHpMagic2,utils.ReplyHpValue2)
	case 3:
		return p.ReplyHpWork(utils.ReplyHpMagic3,utils.ReplyHpValue3)
	}
	return false
}

func (p *Player) ReplyHpWork(magic int32,value int32) bool {
	if p.magic >= magic {
		p.AddMagic(-magic)

		var attackUnitInfoMsg protobuf.AttackUnitInfoMsg

		for _, u := range p.units {
			u.AddHp(value)
			attackUnitInfoMsg.Id = u.Id()
			attackUnitInfoMsg.NowHp = u.NowHp()
			attackUnitInfoMsg.Status = u.Status()
			if u.AttackTarget() != nil {
				attackUnitInfoMsg.AttackId = u.AttackTarget().Id()
			}
			p.gameRoom.Broadcast(protobuf.MsgType_AttackUnitInfo,&attackUnitInfoMsg)
		}
		return true
	}
	return false
}

//修改金币
func (p *Player) AddMoney(money int32) {
	p.money += money
}

//修改魔法值
func (p *Player) AddMagic(magic int32) {
	p.magic += magic
}

//获取当前人口数
func (p *Player) Pop() int32 {
	return p.pop
}

//设置当前人口数
func (p *Player) SetPop(pop int32) {
	p.pop = pop
}


//获取当前魔法每秒增长
func (p *Player) MagicAdd() int32 {
	return p.magicAdd
}

//获取当前魔法值
func (p *Player) Magic() int32 {
	return p.magic
}

//获取当前金币每秒增长
func (p *Player) MoneyAdd() int32 {
	return p.moneyAdd
}

//获取当前金币
func (p *Player) Money() int32 {
	return p.money
}

//添加一个据点
func (p *Player) AddStronghold(stronghold Interface.IStronghold) {
	p.strongholds[stronghold.Id()] = stronghold
}

//移除一个据点
func (p *Player) RemoveStronghold(strongholdId int32) {
	delete(p.strongholds,strongholdId)
}

//获取一个据点
func (p *Player) GetStronghold(strongholdId int32) Interface.IStronghold{
	return p.strongholds[strongholdId]
}

//得到据点的数量
func (p *Player) GetStrongholdNum() int {
	return len(p.strongholds)
}

//新增一个士兵
func (p *Player) AddUnit(unit Interface.IUnit) {
	p.units[unit.Id()] = unit
}

//移除一个士兵
func (p *Player) RemoveUnit(unitId int32) {
	delete(p.units,unitId)
}

//获取一个士兵的
func (p *Player) GetUnit(unitId int32) Interface.IUnit{
	return p.units[unitId]
}

func (p *Player) GameRoom() Interface.IGameRoom {
	return p.gameRoom
}

func (p *Player) User() Interface.IUser {
	return p.user
}

func (p *Player) PlayerId() int32 {
	return p.playerId
}

func (p *Player) Units() map[int32]Interface.IUnit {
	return p.units
}

func (p *Player) FriendId() int32 {
	return p.friendId
}

func (p *Player) SetMaxPop(maxPop int32) {
	p.maxPop = maxPop
}

func (p *Player) MaxPop() int32 {
	return p.maxPop
}
